using System;
using System.Collections;
using System.Data;
using System.Net;
using System.Net.NetworkInformation;
using System.Threading;
using OracleInternal.Common;
using OracleInternal.I18N;
using OracleInternal.ServiceObjects;

namespace Oracle.ManagedDataAccess.Client
{
	public class OracleDependency
	{
		internal OracleDependencyImpl m_orclDependencyImpl;

		private static Hashtable s_depTable;

		private static long m_staticRegistrationId;

		internal string m_guid = Guid.NewGuid().ToString();

		internal string m_dataSource = "";

		internal string m_userName = "";

		private bool m_bHasChanges;

		internal OracleRowidInfo m_OracleRowidInfo = OracleRowidInfo.Default;

		internal bool m_bQueryBasedNTFN = true;

		private object m_syncObject = new object();

		private static string m_defaultHostName;

		private static string m_defaultDomainName;

		internal static Hashtable s_serverIdToClientIdMap;

		public static int Port
		{
			get
			{
				return OracleDependencyImpl.m_portForlistening;
			}
			set
			{
				if (value < -1)
				{
					throw new ArgumentOutOfRangeException("Port");
				}
				if (!OracleNotificationManager.IsListenerRunning())
				{
					OracleDependencyImpl.m_portForlistening = value;
					return;
				}
				throw new InvalidOperationException(OracleStringResourceManager.GetErrorMesg(ResourceStringConstants.NTFN_LISTENER_ALREADY_STARTED));
			}
		}

		public static string Address
		{
			get
			{
				return OracleDependencyImpl.s_machineAddress;
			}
			set
			{
				if (!OracleNotificationManager.IsListenerRunning())
				{
					if (value != null)
					{
						value = value.Trim();
						if (value.StartsWith("["))
						{
							value = value.Trim(']', '[');
						}
					}
					OracleDependencyImpl.s_machineAddress = value;
					if (string.IsNullOrWhiteSpace(value) || string.Compare(value, m_defaultHostName, ignoreCase: true) == 0 || string.Compare(value, m_defaultHostName + "." + m_defaultDomainName) == 0)
					{
						OracleDependencyImpl.m_bIsAddressConfigured = false;
					}
					else if (!string.IsNullOrWhiteSpace(value))
					{
						OracleDependencyImpl.m_bIsAddressConfigured = true;
					}
					return;
				}
				throw new InvalidOperationException(OracleStringResourceManager.GetErrorMesg(ResourceStringConstants.NTFN_LISTENER_ALREADY_STARTED));
			}
		}

		public string DataSource => m_dataSource;

		public bool HasChanges
		{
			get
			{
				bool bHasChanges = m_bHasChanges;
				m_bHasChanges = false;
				return bHasChanges;
			}
		}

		public string Id => m_guid;

		private long InvalidationString => m_orclDependencyImpl.m_clientRegistrationId;

		public bool IsEnabled => m_orclDependencyImpl.m_bIsEnabled;

		public bool QueryBasedNotification
		{
			get
			{
				return m_bQueryBasedNTFN;
			}
			set
			{
				m_bQueryBasedNTFN = value;
			}
		}

		public OracleRowidInfo RowidInfo
		{
			get
			{
				return m_OracleRowidInfo;
			}
			set
			{
				m_OracleRowidInfo = value;
			}
		}

		public ArrayList RegisteredResources => (ArrayList)m_orclDependencyImpl.m_regList.Clone();

		public ArrayList RegisteredQueryIDs => (ArrayList)m_orclDependencyImpl.m_queryIDList.Clone();

		public string UserName => m_userName;

		public event OnChangeEventHandler OnChange;

		static OracleDependency()
		{
			s_depTable = Hashtable.Synchronized(new Hashtable());
			s_serverIdToClientIdMap = Hashtable.Synchronized(new Hashtable());
			if (ProviderConfig.m_bTraceLevelPrivate)
			{
				Trace.Write(OracleTraceLevel.Private, OracleTraceTag.Entry, OracleTraceClassName.OracleDependency, OracleTraceFuncName.cctor);
			}
			if (ConfigBaseClass.m_DBNotificationPort != -1)
			{
				Port = ConfigBaseClass.m_DBNotificationPort;
			}
			m_defaultHostName = Dns.GetHostName();
			m_defaultDomainName = IPGlobalProperties.GetIPGlobalProperties().DomainName;
			if (!string.IsNullOrEmpty(ConfigBaseClass.m_DBNotificationAddress))
			{
				Address = ConfigBaseClass.m_DBNotificationAddress;
			}
			try
			{
				OracleNotificationManager.SetCallbackForNotification(SetNotificationDetails);
			}
			catch (Exception ex)
			{
				OracleException.HandleError(OracleTraceLevel.Private, OracleTraceTag.Error, OracleTraceClassName.OracleDependency, OracleTraceFuncName.cctor, ex);
				throw;
			}
			finally
			{
				if (ProviderConfig.m_bTraceLevelPrivate)
				{
					Trace.Write(OracleTraceLevel.Private, OracleTraceTag.Exit, OracleTraceClassName.OracleDependency, OracleTraceFuncName.cctor);
				}
			}
		}

		public OracleDependency()
		{
			if (ProviderConfig.m_bTraceLevelPublic)
			{
				Trace.Write(OracleTraceLevel.Public, OracleTraceTag.Entry, OracleTraceClassName.OracleDependency, OracleTraceFuncName.ctor);
			}
			try
			{
				m_orclDependencyImpl = new OracleDependencyImpl(OracleNotificationRequest.s_bDefIsNotifiedOnce, OracleNotificationRequest.s_DefRegTimeout, OracleNotificationRequest.s_bDefIsPersistent);
				m_orclDependencyImpl.m_guid = m_guid;
				s_depTable.Add(m_guid, this);
			}
			catch (Exception ex)
			{
				OracleException.HandleError(OracleTraceLevel.Public, OracleTraceTag.Error, OracleTraceClassName.OracleDependency, OracleTraceFuncName.ctor, ex);
				throw;
			}
			finally
			{
				if (ProviderConfig.m_bTraceLevelPublic)
				{
					Trace.Write(OracleTraceLevel.Public, OracleTraceTag.Exit, OracleTraceClassName.OracleDependency, OracleTraceFuncName.ctor);
				}
			}
		}

		public OracleDependency(OracleCommand cmd)
			: this(cmd, OracleNotificationRequest.s_bDefIsNotifiedOnce, OracleNotificationRequest.s_DefRegTimeout, OracleNotificationRequest.s_bDefIsPersistent)
		{
		}

		public OracleDependency(OracleCommand cmd, bool isNotifiedOnce, long timeout, bool isPersistent)
		{
			if (ProviderConfig.m_bTraceLevelPublic)
			{
				Trace.Write(OracleTraceLevel.Public, OracleTraceTag.Entry, OracleTraceClassName.OracleDependency, OracleTraceFuncName.ctor);
			}
			try
			{
				if (cmd == null)
				{
					throw new ArgumentNullException("cmd");
				}
				if (timeout < 0 || timeout > uint.MaxValue)
				{
					throw new ArgumentOutOfRangeException("timeout");
				}
				if (cmd.Notification != null)
				{
					throw new InvalidOperationException(OracleStringResourceManager.GetErrorMesg(ResourceStringConstants.NTFN_CMD_ALREADY_EXIST));
				}
				m_orclDependencyImpl = new OracleDependencyImpl(isNotifiedOnce, timeout, isPersistent);
				m_orclDependencyImpl.m_guid = m_guid;
				long clientRegistrationId = Interlocked.Increment(ref m_staticRegistrationId);
				m_orclDependencyImpl.m_clientRegistrationId = clientRegistrationId;
				OracleNotificationRequest oracleNotificationRequest2 = (cmd.Notification = new OracleNotificationRequest(OracleNotificationRequest.s_ChangedNotificationName, m_orclDependencyImpl));
				s_depTable.Add(m_guid, this);
				if (OracleNotificationRequest.s_idTable[oracleNotificationRequest2.Id] == null)
				{
					OracleNotificationRequest.s_idTable.Add(oracleNotificationRequest2.Id, m_guid);
				}
			}
			catch (Exception ex)
			{
				OracleException.HandleError(OracleTraceLevel.Public, OracleTraceTag.Error, OracleTraceClassName.OracleDependency, OracleTraceFuncName.ctor, ex);
				throw;
			}
			finally
			{
				if (ProviderConfig.m_bTraceLevelPublic)
				{
					Trace.Write(OracleTraceLevel.Public, OracleTraceTag.Exit, OracleTraceClassName.OracleDependency, OracleTraceFuncName.ctor);
				}
			}
		}

		public static OracleDependency GetOracleDependency(string guid)
		{
			if (ProviderConfig.m_bTraceLevelPublic)
			{
				Trace.Write(OracleTraceLevel.Public, OracleTraceTag.Entry, OracleTraceClassName.OracleDependency, OracleTraceFuncName.GetOracleDependency);
			}
			try
			{
				if (guid == null)
				{
					throw new ArgumentNullException("guid");
				}
				return (OracleDependency)s_depTable[guid];
			}
			catch (Exception ex)
			{
				OracleException.HandleError(OracleTraceLevel.Public, OracleTraceTag.Error, OracleTraceClassName.OracleDependency, OracleTraceFuncName.GetOracleDependency, ex);
				throw;
			}
			finally
			{
				if (ProviderConfig.m_bTraceLevelPublic)
				{
					Trace.Write(OracleTraceLevel.Public, OracleTraceTag.Exit, OracleTraceClassName.OracleDependency, OracleTraceFuncName.GetOracleDependency);
				}
			}
		}

		public void AddCommandDependency(OracleCommand cmd)
		{
			if (ProviderConfig.m_bTraceLevelPublic)
			{
				Trace.Write(OracleTraceLevel.Public, OracleTraceTag.Entry, OracleTraceClassName.OracleDependency, OracleTraceFuncName.AddCommandDependency);
			}
			try
			{
				if (cmd == null)
				{
					throw new ArgumentNullException("cmd");
				}
				if (cmd.Notification != null && OracleNotificationRequest.s_idTable[cmd.Notification.Id] != null)
				{
					throw new InvalidOperationException(OracleStringResourceManager.GetErrorMesg(ResourceStringConstants.NTFN_CMD_ALREADY_EXIST));
				}
				if (s_depTable[m_guid] == null)
				{
					s_depTable.Add(m_guid, this);
					m_orclDependencyImpl.m_clientRegistrationId = Interlocked.Increment(ref m_staticRegistrationId);
				}
				cmd.Notification = new OracleNotificationRequest(OracleNotificationRequest.s_ChangedNotificationName, m_orclDependencyImpl);
				if (OracleNotificationRequest.s_idTable[cmd.Notification.Id] == null)
				{
					OracleNotificationRequest.s_idTable.Add(cmd.Notification.Id, m_guid);
				}
			}
			catch (Exception ex)
			{
				OracleException.HandleError(OracleTraceLevel.Public, OracleTraceTag.Error, OracleTraceClassName.OracleDependency, OracleTraceFuncName.AddCommandDependency, ex);
				throw;
			}
			finally
			{
				if (ProviderConfig.m_bTraceLevelPublic)
				{
					Trace.Write(OracleTraceLevel.Public, OracleTraceTag.Exit, OracleTraceClassName.OracleDependency, OracleTraceFuncName.AddCommandDependency);
				}
			}
		}

		public void RemoveRegistration(OracleConnection conn)
		{
			if (ProviderConfig.m_bTraceLevelPublic)
			{
				Trace.Write(OracleTraceLevel.Public, OracleTraceTag.Entry, OracleTraceClassName.OracleDependency, OracleTraceFuncName.RemoveRegistration);
			}
			if (conn == null)
			{
				throw new ArgumentNullException("conn");
			}
			if (!m_orclDependencyImpl.m_bIsRegistered)
			{
				throw new InvalidOperationException(OracleStringResourceManager.GetErrorMesg(ResourceStringConstants.NTFN_REG_NOTVALID));
			}
			if (conn.State != ConnectionState.Open)
			{
				throw new InvalidOperationException(OracleStringResourceManager.GetErrorMesg(ResourceStringConstants.CON_CLOSED));
			}
			try
			{
				if (conn.m_oracleConnectionImpl != null)
				{
					OracleNotificationManager.UnRegisterFromChangeNotification(conn.m_oracleConnectionImpl, m_orclDependencyImpl.m_RegIdFromServer, m_orclDependencyImpl.m_clientId);
				}
			}
			catch (Exception ex)
			{
				OracleException.HandleError(OracleTraceLevel.Public, OracleTraceTag.Error, OracleTraceClassName.OracleDependency, OracleTraceFuncName.RemoveRegistration, ex);
				throw;
			}
			finally
			{
				if (ProviderConfig.m_bTraceLevelPublic)
				{
					Trace.Write(OracleTraceLevel.Public, OracleTraceTag.Exit, OracleTraceClassName.OracleDependency, OracleTraceFuncName.RemoveRegistration);
				}
				m_orclDependencyImpl.m_bIsRegistered = false;
				m_orclDependencyImpl.m_bIsEnabled = false;
			}
			try
			{
				if (s_depTable[m_guid] != null)
				{
					s_depTable.Remove(m_guid);
				}
			}
			catch (Exception ex2)
			{
				OracleException.HandleError(OracleTraceLevel.Public, OracleTraceTag.Error, OracleTraceClassName.OracleDependency, OracleTraceFuncName.RemoveRegistration, ex2);
				throw;
			}
			finally
			{
				if (ProviderConfig.m_bTraceLevelPublic)
				{
					Trace.Write(OracleTraceLevel.Public, OracleTraceTag.Exit, OracleTraceClassName.OracleDependency, OracleTraceFuncName.RemoveRegistration);
				}
			}
			try
			{
				long clientRegistrationId = m_orclDependencyImpl.m_clientRegistrationId;
				if (OracleNotificationRequest.s_idTable[clientRegistrationId] != null)
				{
					OracleNotificationRequest.s_idTable.Remove(clientRegistrationId);
				}
				if (conn.m_oracleConnectionImpl != null && conn.m_oracleConnectionImpl.m_bCanUseSecureCQN)
				{
					try
					{
						s_serverIdToClientIdMap.Remove(m_orclDependencyImpl.m_RegIdFromServer);
					}
					catch
					{
					}
				}
			}
			catch (Exception ex3)
			{
				OracleException.HandleError(OracleTraceLevel.Public, OracleTraceTag.Error, OracleTraceClassName.OracleDependency, OracleTraceFuncName.RemoveRegistration, ex3);
				throw;
			}
			finally
			{
				if (ProviderConfig.m_bTraceLevelPublic)
				{
					Trace.Write(OracleTraceLevel.Public, OracleTraceTag.Exit, OracleTraceClassName.OracleDependency, OracleTraceFuncName.RemoveRegistration);
				}
			}
		}

		public void FiredEvent(OracleNotificationEventArgs e)
		{
			if (ProviderConfig.m_bTraceLevelPublic)
			{
				Trace.Write(OracleTraceLevel.Public, OracleTraceTag.Entry, OracleTraceClassName.OracleDependency, OracleTraceFuncName.FiredEvent);
			}
			try
			{
				if (this.OnChange != null)
				{
					try
					{
						this.OnChange(this, e);
					}
					catch
					{
					}
				}
			}
			catch (Exception ex)
			{
				OracleException.HandleError(OracleTraceLevel.Public, OracleTraceTag.Error, OracleTraceClassName.OracleDependency, OracleTraceFuncName.FiredEvent, ex);
				throw;
			}
			finally
			{
				if (ProviderConfig.m_bTraceLevelPublic)
				{
					Trace.Write(OracleTraceLevel.Public, OracleTraceTag.Exit, OracleTraceClassName.OracleDependency, OracleTraceFuncName.FiredEvent);
				}
			}
		}

		internal void SetRegisterInfo(string username, string dataSource, OracleNotificationRequest ntfnReq)
		{
			if (ProviderConfig.m_bTraceLevelPrivate)
			{
				Trace.Write(OracleTraceLevel.Private, OracleTraceTag.Entry, OracleTraceClassName.OracleDependency, OracleTraceFuncName.SetRegisterInfo);
			}
			try
			{
				m_userName = username;
				m_dataSource = dataSource;
				m_orclDependencyImpl.SetRegisterInfo(ntfnReq.m_bIsNotifiedOnce, ntfnReq.m_bIsPersistent, ntfnReq.m_timeout);
			}
			catch (Exception ex)
			{
				OracleException.HandleError(OracleTraceLevel.Private, OracleTraceTag.Error, OracleTraceClassName.OracleDependency, OracleTraceFuncName.SetRegisterInfo, ex);
				throw;
			}
			finally
			{
				if (ProviderConfig.m_bTraceLevelPrivate)
				{
					Trace.Write(OracleTraceLevel.Private, OracleTraceTag.Exit, OracleTraceClassName.OracleDependency, OracleTraceFuncName.SetRegisterInfo);
				}
			}
		}

		internal static OracleDependency GetOracleDependencyFromNTFNId(long id)
		{
			if (ProviderConfig.m_bTraceLevelPrivate)
			{
				Trace.Write(OracleTraceLevel.Private, OracleTraceTag.Entry, OracleTraceClassName.OracleDependency, OracleTraceFuncName.GetOracleDependencyFromNTFNId);
			}
			try
			{
				string text = null;
				text = (string)OracleNotificationRequest.s_idTable[id];
				if (text != null)
				{
					return (OracleDependency)s_depTable[text];
				}
				return null;
			}
			catch (Exception ex)
			{
				OracleException.HandleError(OracleTraceLevel.Private, OracleTraceTag.Error, OracleTraceClassName.OracleDependency, OracleTraceFuncName.GetOracleDependencyFromNTFNId, ex);
				throw;
			}
			finally
			{
				if (ProviderConfig.m_bTraceLevelPrivate)
				{
					Trace.Write(OracleTraceLevel.Private, OracleTraceTag.Exit, OracleTraceClassName.OracleDependency, OracleTraceFuncName.GetOracleDependencyFromNTFNId);
				}
			}
		}

		internal static void SetNotificationDetails(object notifInfoObj)
		{
			if (ProviderConfig.m_bTraceLevelPrivate)
			{
				Trace.Write(OracleTraceLevel.Private, OracleTraceTag.Entry, OracleTraceClassName.OracleDependency, OracleTraceFuncName.SetNotificationDetails);
			}
			OracleDependency oracleDependency = null;
			try
			{
				short csId = 0;
				int[] array = null;
				int num = 0;
				int num2 = 0;
				bool flag = false;
				byte[] array2 = null;
				int num3 = 1;
				Conv dbCharSetConv = null;
				bool flag2 = false;
				if (notifInfoObj is NotificationInfo)
				{
					flag2 = false;
					NotificationInfo obj = (NotificationInfo)notifInfoObj;
					csId = obj.m_csId;
					array = obj.m_regId;
					flag = obj.m_bTimeoutEvent;
					array2 = obj.m_notifInfo;
					num3 = obj.m_numOfRegistrations;
					goto IL_00d9;
				}
				flag2 = true;
				NotificationContext notificationContext = (NotificationContext)notifInfoObj;
				num = (int)notificationContext.m_regIdFromServer;
				if (s_serverIdToClientIdMap.Contains(num))
				{
					num2 = (int)s_serverIdToClientIdMap[num];
					array = new int[1]
					{
						num2
					};
					array2 = notificationContext.m_payLoad;
					if (array2 == null)
					{
						flag = true;
					}
					dbCharSetConv = notificationContext.m_dbCharSetConv;
					goto IL_00d9;
				}
				goto end_IL_0020;
				IL_00d9:
				OracleNotificationEventArgs oracleNotificationEventArgs = null;
				for (int i = 0; i < num3; i++)
				{
					oracleDependency = GetOracleDependencyFromNTFNId(array[i]);
					if (oracleDependency == null)
					{
						continue;
					}
					OracleDependencyImpl orclDependencyImpl = oracleDependency.m_orclDependencyImpl;
					if (orclDependencyImpl.m_bIsNotifiedOnce)
					{
						orclDependencyImpl.m_bIsRegistered = false;
						orclDependencyImpl.m_bIsEnabled = false;
						try
						{
							s_depTable.Remove(oracleDependency.m_guid);
						}
						catch
						{
						}
						try
						{
							OracleNotificationRequest.s_idTable.Remove(array[i]);
						}
						catch
						{
						}
						if (flag2)
						{
							try
							{
								s_serverIdToClientIdMap.Remove(num);
							}
							catch
							{
							}
							OracleConnectionImpl orclConnImpl = ((NotificationContext)notifInfoObj).m_orclConnImpl;
							if (orclConnImpl != null && orclConnImpl.m_pm != null)
							{
								orclConnImpl.m_pm.RemoveCQNRestration(orclConnImpl.m_listenerClientId, num);
							}
						}
					}
					oracleNotificationEventArgs = ((oracleNotificationEventArgs != null) ? oracleNotificationEventArgs.Clone() : new OracleNotificationEventArgs(new NotificationDetails(csId, dbCharSetConv, num, array2, flag2)));
					if (flag)
					{
						oracleNotificationEventArgs.m_notificationDetails.m_type = OracleNotificationType.Subscribe;
						oracleNotificationEventArgs.m_notificationDetails.m_source = OracleNotificationSource.Subscription;
						oracleNotificationEventArgs.m_notificationDetails.m_info = OracleNotificationInfo.End;
						oracleNotificationEventArgs.m_bInfoNotPopulated = false;
					}
					if (oracleDependency.OnChange == null)
					{
						if (oracleNotificationEventArgs.Source == OracleNotificationSource.Object || oracleNotificationEventArgs.Source == OracleNotificationSource.Data)
						{
							oracleDependency.m_bHasChanges = true;
						}
						break;
					}
					if (oracleNotificationEventArgs.Source == OracleNotificationSource.Database || oracleNotificationEventArgs.Source == OracleNotificationSource.Subscription)
					{
						if (oracleNotificationEventArgs.Source == OracleNotificationSource.Subscription && oracleNotificationEventArgs.Info == OracleNotificationInfo.End)
						{
							orclDependencyImpl.m_bIsRegistered = false;
							orclDependencyImpl.m_bIsEnabled = false;
							try
							{
								s_depTable.Remove(oracleDependency.m_guid);
							}
							catch
							{
							}
							try
							{
								OracleNotificationRequest.s_idTable.Remove(array[i]);
							}
							catch
							{
							}
							if (flag2)
							{
								try
								{
									s_serverIdToClientIdMap.Remove(num);
								}
								catch
								{
								}
							}
						}
						lock (oracleDependency.m_syncObject)
						{
							oracleDependency.FiredEvent(oracleNotificationEventArgs);
						}
						break;
					}
					if (oracleNotificationEventArgs.m_notificationDetails.m_regIdFromServer != orclDependencyImpl.m_RegIdFromServer)
					{
						continue;
					}
					if (oracleDependency.m_bQueryBasedNTFN)
					{
						foreach (long queryId in oracleNotificationEventArgs.QueryIdList)
						{
							if (orclDependencyImpl.m_queryIDList.Contains(queryId))
							{
								continue;
							}
							lock (orclDependencyImpl.m_syncList)
							{
								if (!orclDependencyImpl.m_queryIDList.Contains(queryId))
								{
									orclDependencyImpl.m_queryIDList.Add(queryId);
								}
							}
						}
					}
					lock (oracleDependency.m_syncObject)
					{
						oracleDependency.m_bHasChanges = true;
						oracleDependency.FiredEvent(oracleNotificationEventArgs);
					}
				}
				end_IL_0020:;
			}
			catch (Exception ex)
			{
				OracleException.HandleError(OracleTraceLevel.Private, OracleTraceTag.Error, OracleTraceClassName.OracleDependency, OracleTraceFuncName.SetNotificationDetails, ex);
				throw;
			}
			finally
			{
				if (ProviderConfig.m_bTraceLevelPrivate)
				{
					Trace.Write(OracleTraceLevel.Private, OracleTraceTag.Exit, OracleTraceClassName.OracleDependency, OracleTraceFuncName.SetNotificationDetails);
				}
			}
		}
	}
}
